﻿using Swifter.Json;

namespace RpcHelper.Config
{
    public enum ItemType
    {
        String = 0,
        Num = 3,
        Object = 1,
        Array = 2,
        Boolean = 4,
        Null = -1
    }
    internal class ConfigItem : IConfigItem
    {
        private string _Value = null;
        private readonly IConfig _Source = null;
        private ItemType _ItemType = ItemType.String;
        public ConfigItem(string name, IConfigItem parent, string str, int prower, IConfig source) : this(name, parent, prower, source)
        {
            this._Value = str;
        }

        public ConfigItem(string name, JsonValue token, IConfigItem parent, int prower, IConfig source) : this(name, parent, prower, source)
        {
            this._SetValue(token);
        }
        public ConfigItem(string name, JsonValue token, IConfigItem parent, IConfig source) : this(name, parent, parent.Prower, source)
        {
            this._SetValue(token);
        }
        public ConfigItem(string name, IConfig source)
        {
            this._Source = source;
            this._ItemType = ItemType.Object;
            this.Path = name;
            this.ItemName = name;
        }
        public ConfigItem(string name, IConfigItem parent, int prower, IConfig source)
        {
            this._Source = source;
            this.Path = parent.Path == "root" ? name : string.Concat(parent.Path, ":", name);
            this.Prower = prower;
            this.Parent = parent;
            this.ItemName = name;
        }
        public string Path
        {
            get;
        }
        public IConfigItem Parent
        {
            get;
        }

        public string ItemName
        {
            get;
        }
        public int Prower
        {
            get;
            private set;
        }

        public ItemType ItemType => this._ItemType;

        public bool SetValue(JsonValue obj, int prower)
        {
            if (prower < this.Prower)
            {
                return false;
            }
            else if (this._SetValue(obj))
            {
                this.Prower = prower;
                this._RefreshParent();
                return true;
            }
            return false;
        }
        private bool _SetValue(JsonValue obj)
        {
            if (obj == null)
            {
                if (this._Value == null)
                {
                    return false;
                }
                this._Value = null;
                this._ItemType = ItemType.Null;
                return true;
            }
            else if (obj.IsObject)
            {
                this._ItemType = ItemType.Object;
                return this._SetObject(obj);
            }
            else if (obj.IsArray)
            {
                this._ItemType = ItemType.Array;
                string val = obj.ToString();
                if (val == this._Value)
                {
                    return false;
                }
                this._Value = val;
                this._ItemType = ItemType.Array;
                return true;
            }
            else if (obj.Value is bool i)
            {
                this._ItemType = ItemType.Boolean;
                string val = i.ToString().ToLower();
                if (val == this._Value)
                {
                    return false;
                }
                this._Value = val;
                return true;
            }
            else
            {
                string val = obj.StringValue;
                this._ItemType = ItemType.String;
                if (val == this._Value)
                {
                    return false;
                }
                this._Value = val;
                return true;
            }
        }

        private bool _SetObject(JsonValue dic)
        {
            bool isSet = false;
            foreach (string i in dic.ObjectKeys)
            {
                if (this._Source.SetConfig(i, dic[i], this))
                {
                    isSet = true;
                }
            }
            return isSet;
        }
        public override string ToString()
        {
            if (this._ItemType == ItemType.Object && this._Value == null)
            {
                this._Value = this._Source.GetJson(this.Path);
            }
            return this._Value;
        }

       
    
        private void _RefreshParent()
        {
            if (this.Parent.ItemType == ItemType.Object && this._ItemType != ItemType.Object)
            {
                this.Parent.Refresh();
            }
        }
        public bool SetValue(string obj, ItemType itemType, int prower)
        {
            if (prower < this.Prower || this._Value == obj)
            {
                return false;
            }
            this._ItemType = itemType;
            this.Prower = prower;
            this._Value = obj;
            this._RefreshParent();
            return true;
        }
        public void Refresh()
        {
            if (this.ItemType == ItemType.Object)
            {
                this._Value = null;
                this.Parent?.Refresh();
            }
        }
    }
}
